The Problem.
FlexyFramework, for quite some time has been able to run the bootstrapper in both a 'web view' and on the command line, basically the 'index.php' that is the simple configuration file and start point to every piece of code that runs the framework can be run both form apache, and from the command line called as #php index.php Path/To/Class
Just like the apache requests that map http://yoursite/index.php/Path/To/Class to PROJECTNAME_Path_To_Class, in the same way, the previous command maps to the the same class, and calls the get() method just like a standard web GET request.
This mainly enables you to run code in both scenarios sharing all the same base configuration information, which is normally set in the index.php. The framework includes support for things like 'single instance', so if you run cron jobs you can ensure that the script is only being run by one instance at a time, so long running jobs do not overlap and duplicate the same task.
The only remaining problems with the previous code was that it had a very messy method to deal with 'help' and listing the available classes that could be run on a project. It used to look for a 'Cli.php' class and call that to display some help text. This meant that adding a new cli feature, also meant updating the Cli.php file (which usually just got forgotten about as development pace rarely left time for such niceties). The other issue was that while most classes just provided a simple task when run, a few more complex Cli applications where in need of parameter passing, to debug or test, previously each time argument parsing was done, I either just parsed $_SERVER[argv] or had used one of the PEAR libraries to do argument parsing.
So the bug tracker had an open task to move the 'help' information into the class that actually supplied the code for the Cli, and integrate PEAR's Console_GetArg into the core framework, so that there was a standard way to define what arguments a class would accept, and what it would do.
List of available commands
The Framework in Cli mode, run without arguments, now will actually attempt to load all the .php files inside the Project directory, and test to see if there is a static property $cli_desc is set for the class.
static $cli_desc = "some description"
If this is available it will output a line with the class path, and that description. For the Pman project it outputs something like this.
#php admin.php
-------------------------------------------------
FlexyFramework Cli Application Usage:
#php -d include_path=.:/var/www/pear admin.php [COMMAND] --help
or
#php admin.php [COMMAND] --help
-------------------------------------------------
Available commands:
Builder/RunGenerator Creates Database Tables for modules
Core/JsCompile Wrapper around Javascript compression tools
Core/Notify Send out notification emails (usually from cron)
Core/NotifySend Send out single notification email (usually called from Core/Notify)
Detailed help and command parsing.
Now that I could find the classes with Cli support, the next step was making the documentation available inside the class, a similar method was done for this, each class that has Cli support, can now support a $cli_opts property, which is just the configuration from Console_GetArg
For example, the code in Core/Notify looks like this.
static $cli_opts = array(
'debug' => array(
'desc' => 'Turn on debugging (see DataObjects debugLevel)',
'default' => 0,
'short' => 'v',
'min' => 1,
'max' => 1,
),
'list' => array(
'desc' => 'List message to send, do not send them..',
'default' => 0,
'short' => 'l',
'min' => 0,
'max' => 0,
),
'old' => array(
'desc' => 'Show old messages..',
'default' => 0,
'short' => 'o',
'min' => 0,
'max' => 0,
)
);
and you can now see the help on any Cli applicaiton by simply adding --help to the call, eg.
#php admin.php Core/Notify --help
Usage: php admin.php Core/Notify [-olv]
-v --debug=<value> Turn on debugging (see DataObjects debugLevel ) (0)
-l --list List message to send, do not send them.. (0)
-o --old Show old messages.. (0)
The code that handles the hard work is inside this file (it's only loaded and used when running Cli.